package com.LearnInWorld.search.service.impl;

import com.LearnInWorld.entity.Page;
import com.LearnInWorld.es.pojo.CourseInfo;
import com.LearnInWorld.search.service.SearchService;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.Operator;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.Map;

@Service
public class SearchServiceImpl implements SearchService {

    @Autowired
    private ElasticsearchTemplate esTemplate;

    /**
     * 全文检索
     *
     * @param searchMap 查询参数
     * @return
     * @throws Exception
     */
    @Override
    public Map search(Map<String, String> searchMap) {
        Map<String, Object> map = new HashMap<>();
        //查询条件合法性判断
        if (searchMap == null) {
            return null;
        }
        //原生搜索实现类
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        //关键字查询
        if (StringUtils.hasLength(searchMap.get("keywords"))) {
            //使用boolquery来组装多个查询条件
            // 构建模糊匹配的查询Match，先对搜索字符串进行分词，再做查询，
            // Operator.AND设置分词之后得词语词之间的关系是and还是or
            queryBuilder.must(QueryBuilders.matchQuery("name", searchMap.get("keywords"))
                    .operator(Operator.AND));
        }

        //分类查询
        if (StringUtils.hasLength(searchMap.get("category"))) {
            queryBuilder.filter(QueryBuilders.termQuery("categoryName", searchMap.get("category")));
        }

        nativeSearchQueryBuilder.withQuery(queryBuilder);

        //开启分页
        String pageNum = searchMap.get("pageNum");//当前页
        String pageSize = searchMap.get("pageSize");//每页显示多少页
        if (!StringUtils.hasLength(pageNum)) {
            pageNum = "1";
        }
        if (Integer.parseInt(pageNum) <= 0) {
            pageNum = "1";
        }
        if (!StringUtils.hasLength(pageSize)) {
            pageSize = String.valueOf(Page.pageSize);
        }

        //设置分页
        //第一个参数:当前页 是从0开始
        //第二个参数:每页显示多少条
        nativeSearchQueryBuilder.withPageable(PageRequest.of(Integer.parseInt(pageNum) - 1, Integer.parseInt(pageSize)));


        //设置高亮
        HighlightBuilder.Field field = new HighlightBuilder
                .Field("name")//高亮域
                .preTags("<span style='color:red'>")
                .postTags("</span>"); //高亮样式设置
        nativeSearchQueryBuilder.withHighlightFields(field);

        //开启查询
        /**
         * 第一个参数: 条件构建对象
         * 第二个参数: 查询操作实体类
         * 第三个参数: 查询结果操作对象
         */
        //封装查询结果
        AggregatedPage<CourseInfo> aggregatedPage = esTemplate.queryForPage(nativeSearchQueryBuilder.build(),
                CourseInfo.class, new SearchResultMapperImpl());

        //总记录数
        map.put("total", aggregatedPage.getTotalElements());
        //总页数
        map.put("totalPages", aggregatedPage.getTotalPages());
        //结果集
        map.put("rows", aggregatedPage.getContent());
        //当前页
        map.put("pageNum", pageNum);

        return map;
    }
}
